package com.pt25.base.model.websocket;

import com.pt25.base.model.websocket.handler.*;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class WebsocketChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Resource
    private AuthorizationCheckHandler authorizationCheckHandler;
    @Resource
    private BinaryMessageHandler binaryMessageHandler;
    @Resource
    private TextMessageHandler textMessageHandler;
    @Resource
    private GlobalHandler globalHandler;
    @Resource
    private HeartbeatHandler heartbeatHandler;

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        // websocket 基于http协议，所以要有http编解码器 服务端用HttpServerCodec
        pipeline.addLast(new HttpServerCodec());
        // 对写大数据流的支持
        pipeline.addLast(new ChunkedWriteHandler());
        /*
         * 我们通常接收到的是一个http片段，如果要想完整接受一次请求的所有数据，我们需要绑定HttpObjectAggregator，然后我们
         * 就可以收到一个FullHttpRequest-是一个完整的请求信息。
         *对httpMessage进行聚合，聚合成FullHttpRequest或FullHttpResponse
         * 几乎在netty中的编程，都会使用到此hanler
         */
        pipeline.addLast(new HttpObjectAggregator(1024 * 64));
        // ====================== 以上是用于支持http协议 , 以下是支持httpWebsocket   ======================

        /*
         * 说明参考：https://www.cnblogs.com/sheseido/p/15580024.html
         * authorizationCheckHandler这个handler放第一个的原因是第一次握手的时候，请求实际上还是个http请求， 我可以拿到url中的token完成身份验证的工作。但是完成了之后还需要调用下一个handler完成http到ws协议的升级。
         * WebSocketServerProtocolHandler这个handler是io.netty包中自带的handler用来完成http协议到websocket协议的升级, 并且明确提到消息处理的handler必须在该handler之后。
         */
        pipeline.addLast(authorizationCheckHandler);

        /*
         * 设置心跳检测：10秒未读到数据触发 READER_IDLE
         */
        pipeline.addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS));
        /*
         * websocket 服务器处理的协议，用于指定给客户端连接访问的路由 : /ws
         * 本handler会帮你处理一些繁重的复杂的事
         * 会帮你处理握手动作： handshaking（close, ping, pong） ping + pong = 心跳
         * 对于websocket来讲，都是以frames进行传输的，不同的数据类型对应的frames也不同
         * checkStartsWith：设置为true, 前端websocket url 中才可以传参进行登录验证 new WebSocket("ws://localhost:8088/ws?token=123456")
         */
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws", true));
        //pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        /*
         * 自定义的handler，处理核心业务逻辑
         */
        // 心跳数据处理(需要客户端发心跳信息，否则连接会断开)
        // pipeline.addLast(heartbeatHandler);
        //二进制数据处理
        pipeline.addLast(binaryMessageHandler);
        //文本数据处理
        pipeline.addLast(textMessageHandler);
        /*
         * 异常处理handler
         */
        pipeline.addLast(globalHandler);
    }
}
